package com.zc.mychart.model;

import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.data.Entry;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/2/27 0027.
 */

public class KDJEntrys {
    private List<Entry> Ks;
    private List<Entry> Ds;
    private List<Entry> Js;
    private final int N = 9;

    /**
     * n日RSV=(Cn-Ln)/(Hn-Ln)×100
     * 公式中，Cn为第n日收盘价;Ln为n日内的最低价;Hn为n日内的最高价
     * 其次，计算K值与D值:
     * 当日K值=2/3×前一日K值+1/3×当日RSV
     * 当日D值=2/3×前一日D值+1/3×当日K值
     * 若无前一日K 值与D值，则可分别用50来代替
     * J值=3*当日K值-2*当日D值
     * 以9日为周期的KD线为例，即未成熟随机值，计算公式为
     * 9日RSV=(C-L9)÷(H9-L9)×100
     * 公式中，C为第9日的收盘价;L9为9日内的最低价;H9为9日内的最高价
     * K值=2/3×第8日K值+1/3×第9日RSV
     * D值=2/3×第8日D值+1/3×第9日K值
     * J值=3*第9日K值-2*第9日D值
     * 若无前一日K 值与D值，则可分别用50来代替
     */
    public KDJEntrys(List<CandleEntry> list) {
        Ks = new ArrayList<>();
        Ds = new ArrayList<>();
        Js = new ArrayList<>();
        float k = 50.0f;
        float d = 50.0f;
        float j = 0.0f;
        float rsv = 0.0f;
        if (list != null && list.size() > 0) {
            float high;
            float low;
            for (int i = N - 1; i < list.size(); i++) {
                Float[] wrs = getHighAndLowByK(i, list);
                high = wrs[0];
                low = wrs[1];
                if (high != low) {
                    rsv = (list.get(i).getClose() - low) / (high - low) * 100;
                } else {
                    rsv = 0;
                }
                k = k * 2 / 3 + rsv / 3;
                d = d * 2 / 3 + k / 3;
                j = (3 * k) - (2 * d);

                //其他软件没有大于100小于0的值，但是我算出来确实有，其它软件在0和100的时候出现直线，怀疑也是做了处理
                j = j < 0 ? 0 : j;
                j = j > 100 ? 100 : j;
                float x = list.get(i).getX();
                Ks.add(new Entry(x, k));
                Ds.add(new Entry(x, d));
                Js.add(new Entry(x, j));
            }
        }
    }

    /**
     * 得到某区间内最高价和最低价
     *
     * @param end 结束位置
     */
    private Float[] getHighAndLowByK(int end, List<CandleEntry> list) {
        CandleEntry candleEntry = list.get(end);
        float high = candleEntry.getHigh();
        float low = candleEntry.getLow();
        Float[] wrs = new Float[2];
        for (int j = 0; j < N; j++) {
            candleEntry = list.get(end - j);
            high = high > candleEntry.getHigh() ? high : candleEntry.getHigh();
            low = low < candleEntry.getLow() ? low : candleEntry.getLow();
        }
        wrs[0] = high;
        wrs[1] = low;
        return wrs;
    }

    public List<Entry> getKs() {
        return Ks;
    }

    public List<Entry> getDs() {
        return Ds;
    }

    public List<Entry> getJs() {
        return Js;
    }
}
